Skip to content

Conversation

@abretonc7s
Copy link
Contributor

@abretonc7s abretonc7s commented Oct 18, 2025

Description

This PR implements TAT-1729, adding expected profit/loss calculation display to the Auto Close (TP/SL) configuration screen. It also includes several UX improvements based on design refinements.

What is the reason for the change?

Users need to see the expected net profit or loss when setting TP/SL values, accounting for trading fees. This helps them make informed decisions about their risk management strategy. Additionally, several UX improvements were needed to match the final design specifications.

What is the improvement/solution?

  1. Expected P&L Display: Shows real-time expected profit/loss below TP and SL input fields

    • Calculates net P&L by deducting MetaMask and protocol fees from gross profit/loss
    • Dynamically displays "Expected profit: $X.XX" or "Expected loss: $X.XX" based on the net value
    • Handles edge cases where TP creates loss or SL creates profit (for modified positions)
    • Right-aligned text in BodyMD font with Alternative color
    • Formats values using existing formatPerpsFiat with PRICE_RANGES_MINIMAL_VIEW
  2. Terminology Update: Renamed "TP/SL" to "Auto close" throughout the UI

    • Order view: "Auto close" label
    • All user-facing strings updated
    • Technical abbreviations "TP" and "SL" retained for compact displays
  3. UX Improvements:

    • Centered header title with absolute positioned back button
    • "Clear" action buttons positioned on same row as section titles (right-aligned)
    • Dollar symbol ($) positioned on LEFT of input fields (matching currency convention)
    • Removed explainer text at top of view
    • Percentage buttons no longer stay selected after press (cleaner UI)
    • Auto-scroll to keep inputs visible when custom keypad is active
    • Action buttons: "Cancel" + "Set" when keypad inactive, "Done" when keypad active
  4. Implementation Approach (DRY):

    • Reuses existing calculatePnL() utility from pnlCalculations.ts
    • Reuses existing usePerpsOrderFees() hook for accurate fee calculation
    • Reuses existing calculatePositionSize() for new orders
    • Adds small calculateExpectedPnL() wrapper that combines P&L with fee deduction
    • Extends usePerpsTPSLForm hook return values (no new hooks created)
    • Reuses existing formatting utilities (formatPerpsFiat)
    • Uses custom Keypad component (no native keyboard, no timeout needed)

Changelog

CHANGELOG entry: Added expected profit/loss display to Auto Close (TP/SL) configuration showing net profit after fees, improved UI layout and terminology

Related issues

Manual testing steps

Feature: Expected Profit/Loss Display for Auto Close (TP/SL)

  Scenario: User sets Take Profit for new long position
    Given user is on the Order View screen for BTC
    And user enters an order amount of $100 at 2x leverage
    When user taps "Auto close"
    And user sets Take Profit to $105,000 (assuming current price is $100,000)
    Then user sees "Expected profit: $X.XX" below the TP input (right-aligned, BodyMD, Alternative color)
    And the amount accounts for closing fees

  Scenario: User sets Stop Loss for new short position
    Given user is on the Order View screen for ETH
    And user enters a short order amount of $50 at 3x leverage
    When user taps "Auto close"
    And user sets Stop Loss to $3,200 (assuming current price is $3,000)
    Then user sees "Expected loss: $X.XX" below the SL input (right-aligned, BodyMD, Alternative color)
    And the amount accounts for closing fees

  Scenario: User modifies TP/SL for existing position
    Given user has an existing long position in BTC
    And user taps "Edit TP/SL" from position card
    When user sets Take Profit to $110,000
    And user sets Stop Loss to $95,000
    Then user sees expected profit below TP input
    And user sees expected loss below SL input
    And both values are calculated from actual position entry price

  Scenario: Edge case - TP creates loss on modified position
    Given user has a long position with entry price $100,000
    And current price has moved down to $95,000
    When user sets Take Profit at $98,000 (still below entry)
    Then user sees "Expected loss: $X.XX" (smaller loss than current)
    And text is displayed in Alternative color (not Error color)

  Scenario: Verify UI improvements
    Given user is viewing the Auto Close screen
    Then user sees centered "Auto close" title with back button on left
    And "Clear" buttons appear on same row as "Take Profit" and "Stop Loss" titles (right-aligned)
    And dollar symbol "$" appears on LEFT of price input fields
    And percentage buttons do not stay selected after press
    And no explainer text appears at top of screen

  Scenario: Verify action buttons behavior
    Given user is on the Auto Close screen
    When keypad is NOT active
    Then user sees "Cancel" button (left) and "Set" button (right)
    When user taps any price or percentage input
    Then keypad appears and user sees only "Done" button
    When user taps "Done"
    Then keypad dismisses and user sees "Cancel" and "Set" buttons again

  Scenario: Verify auto-scroll for custom keypad
    Given user is on the Auto Close screen
    When user taps Take Profit price input
    Then view scrolls to offset 150px to keep input visible
    When user taps Stop Loss price input
    Then view scrolls to offset 350px to keep input visible
    And user can still manually scroll to see current price info

Screenshots/Recordings

Before

After

Screen.Recording.2025-10-18.at.7.43.52.PM.mov

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Displays fee-adjusted expected profit/loss in the TPSL view, passes needed params from Order view, and updates layout/strings and validations.

  • Perps TPSL (Auto close):
    • Expected PnL: Compute and display net expected PnL for TP/SL using calculateExpectedPnL, usePerpsOrderFees, and calculatePositionSize; added to usePerpsTPSLForm (expectedTakeProfitPnL, expectedStopLossPnL).
    • Params: PerpsOrderView now passes amount and szDecimals to Routes.PERPS.TPSL; nav types extended.
    • UI/UX:
      • Header centered title with absolute back button; section-row "Clear" actions; $ label moved left of inputs; non-sticky percentage buttons.
      • Footer buttons now "Cancel" + "Set" (keypad inactive) and "Done" (keypad active); auto-scroll on input focus; muted backgrounds and refined styles.
    • Logic/Validation: More robust direction handling; safeguards in RoE calculations; keypad dismissal flow improved.
  • Utilities:
    • Added calculateExpectedPnL in utils/pnlCalculations.
    • Minor tweaks in tpslValidation (direction checks, mixed sign handling).
  • Strings:
    • Renamed "TP/SL" to "Auto close" and added new labels: cancel, set, clear, expected_profit/loss.
  • Tests:
    • Updated/expanded TPSL view and hook tests to cover new UI, formatting, and behaviors.
  • Misc:
    • Improved error propagation in usePerpsTPSLUpdate.
    • Minor type/format fixes in Predict provider types.

Written by Cursor Bugbot for commit 4ac0c9d. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added team-earn INVALID-PR-TEMPLATE PR's body doesn't match template labels Oct 18, 2025
@abretonc7s abretonc7s marked this pull request as ready for review October 18, 2025 11:48
@abretonc7s abretonc7s requested a review from a team as a code owner October 18, 2025 11:48
@abretonc7s abretonc7s added team-perps Perps team and removed INVALID-PR-TEMPLATE PR's body doesn't match template team-earn labels Oct 18, 2025
@github-actions github-actions bot added size-L and removed size-M labels Oct 19, 2025
cursor[bot]

This comment was marked as outdated.

@github-actions github-actions bot added size-XL and removed size-L labels Oct 20, 2025
cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

cursor[bot]

This comment was marked as outdated.

@gambinish gambinish removed the request for review from a team October 21, 2025 16:18
@gambinish
Copy link
Contributor

gambinish commented Oct 21, 2025

Screenshot 2025-10-21 at 9 33 07 AM

Hmm I'm still seeing a rounding issue here. Is 5 decimal places expected behavior?

Could we just use Intl.NumberFormat directly here to keep to 2 decimal places?

EDIT: Actually, it looks like this is how we're handling token balances in fiat throughout the Perps domain. I'll verify that this is expected before approving.

@nickewansmith
Copy link
Contributor

I noticed that the gap between SL clear button and TP Expected profit section becomes very small when the keyboard is open.

Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-10-21.at.12.29.55.mp4

@gambinish gambinish enabled auto-merge October 21, 2025 20:35
effectiveEntryPrice = spotPrice;
} else {
effectiveEntryPrice = livePrice || initialCurrentPrice || 0;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Entry Price Handling Regression

The effectiveEntryPrice calculation in PerpsTPSLView.tsx no longer correctly handles position.entryPrice values of "0" or "0.00". The previous logic would fall back to other price sources in these cases, but the updated code now uses 0 as the effective entry price, which can lead to incorrect calculations.

Fix in Cursor Fix in Web

// Notional value must be positive for fee calculation (use abs for short positions)
const tpNotionalValue =
takeProfitPrice && positionSizeForPnL !== 0
? (parseFloat(takeProfitPrice) * Math.abs(positionSizeForPnL)).toFixed(2)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Non-numeric Prices Cause Fee Calculation Errors

When takeProfitPrice or stopLossPrice contain non-numeric characters, parseFloat returns NaN. This causes tpNotionalValue and slNotionalValue to become the string "NaN" after toFixed(2). Passing "NaN" as the amount to usePerpsOrderFees may lead to incorrect fee calculations for expected P&L.

Additional Locations (1)

Fix in Cursor Fix in Web

@sonarqubecloud
Copy link

@gambinish gambinish added this pull request to the merge queue Oct 21, 2025
Merged via the queue into main with commit 483b6bd Oct 21, 2025
82 of 83 checks passed
@gambinish gambinish deleted the feat/perps/newtpsl branch October 21, 2025 21:18
@github-actions github-actions bot locked and limited conversation to collaborators Oct 21, 2025
@metamaskbot metamaskbot added release-7.59.0 Issue or pull request that will be included in release 7.59.0 release-7.58.0 Issue or pull request that will be included in release 7.58.0 and removed release-7.59.0 Issue or pull request that will be included in release 7.59.0 labels Oct 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.58.0 Issue or pull request that will be included in release 7.58.0 size-XL team-perps Perps team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants